#include "pile.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

int NbReg = 0;


struct pile_var * initPileVar()
{
  struct pile_var * p = malloc(sizeof(struct pile_var));
  p->premier_glo=NULL;
  p->dernier_glo=NULL;
  p->premier_loc=NULL;
  p->dernier_loc=NULL;
  return p;
}

struct pile_var * reInitPileLoc(struct pile_var * p0)
{
  struct pile_var * p1 = malloc(sizeof(struct pile_var));
  p1->premier_glo=p0->premier_glo;
  p1->dernier_glo=p0->dernier_glo;
  p1->premier_loc=NULL;
  p1->dernier_loc=NULL;
  return p1;
}


void ajouterVar(struct pile_var * p, char* id)
{
  struct var * s = malloc(sizeof(struct var));
  s->id=strdup(id);
  s->type = UNDEF;
  s->arg = 0;
  char reg[254];
  if(id[0] == '$'){
    sprintf(reg,"@u%d",NbReg);
    if(p->premier_glo == NULL)
    {
      p->premier_glo = s;
      p->dernier_glo = s;
      s->suivant = NULL;
      s->suivant = NULL;
    }
  else
    {
      p->dernier_glo->suivant = s;
      s->precedent = p->dernier_glo;
      p->dernier_glo = s;
      s->suivant = NULL;
    }
  }
  else
    {
      sprintf(reg,"%%u%d",NbReg);
      if(p->premier_loc == NULL)
	{
	  p->premier_loc = s;
	  p->dernier_loc = s;
	  s->suivant = NULL;
	  s->precedent = NULL;
	}
      else
	{
	  p->dernier_loc->suivant = s;
	  s->precedent = p->dernier_loc;
	  p->dernier_loc = s;
	  s->suivant = NULL;
	}
    } 
  NbReg++;
  s->reg=strdup(reg);
}

int estBegin(struct var * v)
{
  return v->type == BLOCK; 
}

struct var * getVar(struct pile_var * p, char * id)
{
  struct var * ret = p->dernier_loc;
  if(ret!=NULL)
    {
      while(ret != p->premier_loc)
	{
	  if(!estBegin(ret))
	    {
	      if (strcmp(ret->id,id)==0)
		return ret;
	    }	      
	  ret = ret->precedent;
	}
      if(!estBegin(ret))
	{
	  if(strcmp(ret->id,id)==0)
	    return ret;
	}
    }
  ret = p->dernier_glo;
  if(ret!=NULL)
    {
      while(ret != p->premier_glo)
	{
	  if (strcmp(ret->id,id)==0)
	    return ret;
	  else 
	    ret = ret->precedent;
	}
      if(strcmp(ret->id,id)==0)
	return ret;
    }
  return NULL;
}

void libererVar(struct var * v)
{
  // FUITE MEMOIRE !!!!!!
}

void empilerSent(struct pile_var * p)
{
  struct var * v = malloc(sizeof (struct var));
  if(p->premier_loc == NULL)
    {
      p->premier_loc = v;
      p->dernier_loc = v;
      v->suivant = NULL;
      v->precedent = NULL;
    }
  else
    {
      p->dernier_loc->suivant = v;
      v->precedent = p->dernier_loc;
      p->dernier_loc = v;
      v->suivant = NULL;
    }
  v->type = BLOCK;
}

void depiler(struct pile_var * p)
{
  struct var * v = p->dernier_loc;
  
  while(!estBegin(v))
    {
      p->dernier_loc = v->precedent;
      libererVar(v);
      v = p->dernier_loc;
    }
  p->dernier_loc = v->precedent;
  if(p->dernier_loc == NULL)
    p->premier_loc = NULL;
  libererVar(v);
  
}


void setVarArg(struct pile_var * p, char * id)
{
  struct var * v = getVar(p,id);
  v->arg = 1;
}

int estVarArg(struct pile_var * p, char * id)
{
  struct var * v = getVar(p,id);
  return v->arg;
}

void setVarType(struct pile_var * p, char * id, int type)
{
  struct var * v = getVar(p,id);
  v->type = type;
}

int typeVar(struct pile_var * p, char * id)
{
  struct var * v = getVar(p,id);
  if(v == NULL)
    return UNDEF;
  return v->type;
}

int existeVar(struct pile_var * p, char * id)
{
  struct var * v = getVar(p,id);
  return v != NULL;
}

char * regVar(struct pile_var * p, char * id)
{
  struct var * v = getVar(p,id);
  return v->reg;
}



//Fonction
void ajouterFonc(struct pile_fonc * p, char * nom, char* type, int type_ret)
{
  struct fonc * f = malloc(sizeof(struct fonc));
  f->reg=strdup(nom);
  f->type = strdup(type);
  f->type_ret = type_ret;
  if(p->premier == NULL)
    {
      p->premier = f;
      p->dernier = f;
      f->suivant = NULL;
      f->precedent = NULL;
    }
  else
    {
      p->dernier->suivant = f;
      f->precedent = p->dernier;
      p->dernier = f;
      f->suivant = NULL;
    }
}

struct fonc * getFonc(struct pile_fonc* p,char *nom)
{
  struct fonc * f = p->dernier;
  while(f != NULL)
    {
      if(strcmp(f->reg,nom)==0)
	{
	  return f;
	}
      f = f->precedent;
    }
  return NULL;
}

char * getFoncType(struct pile_fonc* p,char *nom)
{
  return getFonc(p,nom)->type;
}

int getFoncTypeRet(struct pile_fonc* p,char *nom)
{
  return getFonc(p,nom)->type_ret;
}

int existeFonc(struct pile_fonc* p,char *nom)
{
  return getFonc(p,nom)!=NULL;
}

struct pile_fonc * initPileFonc()
{
  struct pile_fonc * p = malloc(sizeof(struct pile_fonc));
  p->dernier=NULL;
  p->premier=NULL;
  return p;
}

/*
struct pile_type ptype;

void ajouterType(char* nom)
{
  struct type * t = malloc(sizeof(struct type));
  t->nom=strdup(nom);
  ptype.dernier->suivant=t;
  ptype.dernier = t;
  t->suivant = NULL;
  ptype.nb++;
  }*/
